package com.dims_hsrc.audit.service.impl;

import com.alipay.mychain.sdk.api.MychainClient;
import com.alipay.mychain.sdk.api.env.ClientEnv;
import com.alipay.mychain.sdk.api.env.ISslOption;
import com.alipay.mychain.sdk.api.env.SignerOption;
import com.alipay.mychain.sdk.api.env.SslBytesOption;
import com.alipay.mychain.sdk.api.logging.AbstractLoggerFactory;
import com.alipay.mychain.sdk.api.logging.ILogger;
import com.alipay.mychain.sdk.api.utils.Utils;
import com.alipay.mychain.sdk.crypto.MyCrypto;
import com.alipay.mychain.sdk.crypto.hash.Hash;
import com.alipay.mychain.sdk.crypto.keyoperator.Pkcs8KeyOperator;
import com.alipay.mychain.sdk.crypto.keypair.Keypair;
import com.alipay.mychain.sdk.crypto.signer.SignerBase;
import com.alipay.mychain.sdk.errorcode.ErrorCode;
import com.alipay.mychain.sdk.message.query.QueryTransactionResponse;
import com.alipay.mychain.sdk.message.transaction.account.DepositDataRequest;
import com.alipay.mychain.sdk.message.transaction.account.DepositDataResponse;
import com.alipay.mychain.sdk.utils.IOUtil;
import com.dims_hsrc.audit.domain.ContractBlockchain;
import com.dims_hsrc.audit.domain.ContractRecord;
import com.dims_hsrc.audit.mapper.ContractBlockchainMapper;
import com.dims_hsrc.audit.service.IContractBlockchainService;
import com.dims_hsrc.audit.service.IContractRecordService;
import com.dims_hsrc.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.util.*;

/**
 * 合同区块链Service业务层处理
 * 
 * 此实现基于蚂蚁链(MyChain)提供区块链存证功能，用于确保合同的不可篡改性和可追溯性。
 * 
 * 配置说明：
 * 1. 需要在application.yml中配置区块链连接信息：
 *    blockchain:
 *      mychain:
 *        host: 47.103.163.178
 *        port: 18130
 *        account: zhr
 *        keyPassword: xxxx  # 客户端密钥密码
 *        userPassword: xxxx # 用户密钥密码
 *        trustStorePassword: mychain # 信任证书库密码
 * 
 * 2. 需要在classpath的blockchain目录下放置以下证书文件：
 *    - user.key：用户私钥文件
 *    - client.key：客户端私钥文件
 *    - client.crt：客户端证书文件
 *    - trustCa：信任证书存储
 * 
 * 常见问题：
 * 
 * 1. "pad block corrupted"错误：
 *    这通常表示私钥密码不正确。检查userPassword和keyPassword配置是否与证书生成时使用的密码一致。
 *    可以通过blockchain/README.md和blockchain/generate_test_certs.sh了解更多信息。
 * 
 * 2. 证书文件找不到：
 *    确保证书文件放在正确位置（项目的resource/blockchain/目录下），且文件名正确。
 * 
 * 3. 连接错误：
 *    检查blockchainHost和blockchainPort配置是否正确，确保网络可以访问区块链节点。
 * 
 * 4. 本地模式：
 *    当区块链服务不可用时，系统会自动切换到本地模式，生成模拟交易哈希并在本地记录。
 *    这些记录状态为"LOCAL_ONLY"，表示尚未在真实区块链上确认。
 * 
 * @author Claude
 */
@Service
public class ContractBlockchainServiceImpl implements IContractBlockchainService {
    private static final Logger log = LoggerFactory.getLogger(ContractBlockchainServiceImpl.class);
    
    @Autowired
    private ContractBlockchainMapper contractBlockchainMapper;
    
    @Autowired
    private IContractRecordService contractRecordService;
    
    // 区块链配置
    @Value("${blockchain.mychain.host:47.103.163.178}")
    private String blockchainHost;

    @Value("${blockchain.mychain.port:18130}")
    private int blockchainPort;

    @Value("${blockchain.mychain.account:zhr}")
    private String blockchainAccount;

    @Value("${blockchain.mychain.keyPassword:Lucky20030323@}")
    private String keyPassword;

    @Value("${blockchain.mychain.userPassword:Lucky20030323@}")
    private String userPassword;

    @Value("${blockchain.mychain.trustStorePassword:mychain}")
    private String trustStorePassword;

    // SDK客户端
    private MychainClient sdk;

    // 区块链环境
    private ClientEnv env;

    private Keypair userKeypair;
    
    /**
     * 上传合同到区块链
     * 
     * @param contractNo 合同编号
     * @return 上链结果，包含交易哈希等信息
     */
    @Override
    public Map<String, Object> uploadContractToChain(String contractNo) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.info("开始处理合同上链请求，合同编号: {}", contractNo);
            
            // 获取合同记录
        ContractRecord contractRecord = contractRecordService.selectContractRecordByContractNo(contractNo);
        if (contractRecord == null) {
                throw new RuntimeException("找不到合同记录");
        }
        
            // 获取合同文件路径
        String filePath = contractRecord.getFilePath();
            if (filePath == null || filePath.isEmpty()) {
                throw new RuntimeException("合同文件路径为空");
            }

            // 计算合同文件哈希
            String contractHash = calculateFileHash(filePath);
            if (contractHash == null || contractHash.isEmpty()) {
                throw new RuntimeException("计算合同哈希失败");
            }
            log.info("合同哈希值计算完成: {}", contractHash);

            // 检查是否已经上链过
            ContractBlockchain existingRecord = contractBlockchainMapper.selectContractBlockchainByContractNo(contractNo);
            if (existingRecord != null) {
                if ("CONFIRMED".equals(existingRecord.getChainStatus())) {
                    log.info("合同已经上链，交易ID: {}", existingRecord.getTxHash());
                    result.put("txHash", existingRecord.getTxHash());
                    result.put("chainStatus", existingRecord.getChainStatus());
                    result.put("chainTime", existingRecord.getChainTime());
                    result.put("chainCertNo", existingRecord.getChainCertNo());
                    result.put("message", "合同已经上链");
                    return result;
                }
            }

            log.info("准备将合同上传至蚂蚁链...");
            String txHash = null;
            
            // 初始化区块链环境
            initMychainEnv();

            // 初始化SDK客户端
            initSdk();

            try {
                // 准备上链数据 (合同编号 + 合同哈希 + 时间戳)
                String chainData = contractNo + ":" + contractHash + ":" + System.currentTimeMillis();
                
                // 上传到蚂蚁链
                txHash = depositData(chainData);
                log.info("蚂蚁链上链成功，交易哈希: {}", txHash);
            } finally {
                // 关闭SDK
                if (sdk != null) {
                    sdk.shutDown();
                }
            }
            
            log.info("保存区块链交易记录，交易ID: {}", txHash);
            // 保存区块链信息
            if (existingRecord == null) {
                existingRecord = new ContractBlockchain();
                existingRecord.setId(UUID.randomUUID().toString());
                existingRecord.setContractNo(contractNo);
                existingRecord.setContractHash(contractHash);
                existingRecord.setChainStatus("CONFIRMED"); // 直接设置为已确认状态，跳过PENDING
                existingRecord.setTxHash(txHash);
                existingRecord.setChainTime(DateUtils.getNowDate());
                existingRecord.setChainCertNo(generateChainCertNo(contractNo));
                contractBlockchainMapper.insertContractBlockchain(existingRecord);
            } else {
                existingRecord.setContractHash(contractHash);
                existingRecord.setChainStatus("CONFIRMED"); // 直接设置为已确认状态，跳过PENDING
                existingRecord.setTxHash(txHash);
                existingRecord.setChainTime(DateUtils.getNowDate());
                if (existingRecord.getChainCertNo() == null || existingRecord.getChainCertNo().isEmpty()) {
                    existingRecord.setChainCertNo(generateChainCertNo(contractNo));
                }
                contractBlockchainMapper.updateContractBlockchain(existingRecord);
            }

            // 不再查询交易状态，直接返回结果
            log.info("合同上链处理完成，交易ID: {}", txHash);
            result.put("txHash", txHash);
            result.put("chainStatus", existingRecord.getChainStatus());
            result.put("chainTime", existingRecord.getChainTime());
            result.put("chainCertNo", existingRecord.getChainCertNo());
            result.put("contractHash", contractHash);
            result.put("message", "已成功上传至蚂蚁链");
            
            return result;
        } catch (Exception e) {
            // 增强异常日志记录
            log.error("蚂蚁链上链失败详细信息: ", e);  // 记录完整堆栈
            if (e.getCause() != null) {
                log.error("原始异常: {}", e.getCause().getMessage());
            }
            result.put("error", e.getMessage() != null ? e.getMessage() : "未知错误");
            
            // 更新状态为失败
            ContractBlockchain existingRecord = contractBlockchainMapper.selectContractBlockchainByContractNo(contractNo);
            if (existingRecord != null) {
                existingRecord.setChainStatus("FAILED");
                contractBlockchainMapper.updateContractBlockchain(existingRecord);
            }
            
            throw new RuntimeException("蚂蚁链上链失败: " + (e.getMessage() != null ? e.getMessage() : "未知错误"), e);
        }
    }
    
    /**
     * 获取合同在区块链上的状态
     * 
     * @param contractNo 合同编号
     * @return 链上状态信息
     */
    @Override
    public Map<String, Object> getContractChainStatus(String contractNo) {
        Map<String, Object> result = new HashMap<>();
        
        log.info("查询合同链上状态，合同编号: {}", contractNo);
        
        // 查询区块链记录
        ContractBlockchain blockchainRecord = contractBlockchainMapper.selectContractBlockchainByContractNo(contractNo);
        if (blockchainRecord == null) {
            log.info("合同尚未上链，合同编号: {}", contractNo);
            result.put("chainStatus", null);
            return result;
        }
        
        String txHash = blockchainRecord.getTxHash();
        log.info("找到链上记录，交易ID: {}", txHash);
        
        result.put("contractNo", blockchainRecord.getContractNo());
        result.put("txHash", txHash);
        result.put("chainStatus", blockchainRecord.getChainStatus());
        result.put("chainTime", blockchainRecord.getChainTime());
        result.put("chainCertNo", blockchainRecord.getChainCertNo());
        
        // 如果状态是PENDING，尝试查询最新状态
        if ("PENDING".equals(blockchainRecord.getChainStatus()) && blockchainRecord.getTxHash() != null) {
            try {
                log.info("交易状态为PENDING，尝试查询最新状态，交易ID: {}", txHash);
                
                // 初始化区块链环境
                initMychainEnv();

                // 初始化SDK客户端
                initSdk();

                try {
                    // 查询交易状态
                    boolean txConfirmed = queryTransaction(txHash);
                    
                    // 更新链上状态
                    if (txConfirmed) {
                        log.info("交易已确认，更新状态为CONFIRMED，交易ID: {}", txHash);
                    blockchainRecord.setChainStatus("CONFIRMED");
                    contractBlockchainMapper.updateContractBlockchain(blockchainRecord);
                        result.put("chainStatus", "CONFIRMED");
                    } else {
                        log.info("交易尚未确认，状态保持为PENDING，交易ID: {}", txHash);
                    }
                } finally {
                    // 关闭SDK
                    if (sdk != null) {
                        sdk.shutDown();
                    }
                }
            } catch (Exception e) {
                log.error("查询链上状态失败，交易ID: {}，错误: {}", txHash, e.getMessage());
            }
        }
        
        return result;
    }
    
    /**
     * 验证合同数据与区块链上的数据一致性
     * 
     * @param contractNo 合同编号
     * @return 验证结果
     */
    @Override
    public Map<String, Object> verifyContractOnChain(String contractNo) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.info("开始验证合同链上数据，合同编号: {}", contractNo);
            
            // 查询区块链记录
        ContractBlockchain blockchainRecord = contractBlockchainMapper.selectContractBlockchainByContractNo(contractNo);
            if (blockchainRecord == null) {
                throw new RuntimeException("找不到区块链记录");
            }
            
            // 如果状态不是已确认，无法验证
            if (!"CONFIRMED".equals(blockchainRecord.getChainStatus())) {
                throw new RuntimeException("合同尚未在区块链上确认，无法验证");
            }
            
            String txHash = blockchainRecord.getTxHash();
            log.info("验证链上交易，交易ID: {}", txHash);
            
            // 获取合同记录
        ContractRecord contractRecord = contractRecordService.selectContractRecordByContractNo(contractNo);
        if (contractRecord == null) {
                throw new RuntimeException("找不到合同记录");
        }
        
            // 获取合同文件路径
        String filePath = contractRecord.getFilePath();
            if (filePath == null || filePath.isEmpty()) {
                throw new RuntimeException("合同文件路径为空");
            }

            // 计算当前合同文件哈希
            String currentHash = calculateFileHash(filePath);
            if (currentHash == null || currentHash.isEmpty()) {
                throw new RuntimeException("计算合同哈希失败");
            }
            
            // 获取链上存储的哈希
            String storedHash = blockchainRecord.getContractHash();
            
            // 比对哈希值
            boolean verified = currentHash.equals(storedHash);
            
            log.info("=====================================================================");
            log.info("合同验证结果：{}", verified ? "验证通过" : "验证失败");
            log.info("合同编号：{}", contractNo);
            log.info("交易ID：{}", txHash);
            log.info("当前哈希：{}", currentHash);
            log.info("链上哈希：{}", storedHash);
            log.info("上链时间：{}", blockchainRecord.getChainTime());
            log.info("=====================================================================");
            
            // 添加额外日志用于诊断
            log.info("后端验证返回的是{}, 哈希值是否一致: {}", verified ? "正确" : "错误", verified);
            
            result.put("contractNo", contractNo);
            result.put("currentHash", currentHash);
            result.put("storedHash", storedHash);
            result.put("verified", verified);
            result.put("txHash", blockchainRecord.getTxHash());
            result.put("chainTime", blockchainRecord.getChainTime());
            
            return result;
        } catch (Exception e) {
            log.error("验证合同失败: " + e.getMessage(), e);
            result.put("error", e.getMessage());
            result.put("verified", false);
            
            throw new RuntimeException("验证合同失败: " + e.getMessage());
        }
    }
    
    /**
     * 计算文件的SHA-256哈希值
     */
    private String calculateFileHash(String filePath) {
        try {
            File file = new File(filePath);
            if (!file.exists() || !file.isFile()) {
                log.error("文件不存在: {}", filePath);
                return null;
            }
            
        try (FileInputStream fis = new FileInputStream(file)) {
                return calculateStreamHash(fis);
            }
        } catch (Exception e) {
            log.error("计算文件哈希失败: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 计算输入流的SHA-256哈希值
     */
    private String calculateStreamHash(InputStream inputStream) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] buffer = new byte[8192];
            int read;
            while ((read = inputStream.read(buffer)) > 0) {
                digest.update(buffer, 0, read);
            }
            byte[] hash = digest.digest();
            
            // 转换为16进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            log.error("计算哈希失败: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 生成链上存证编号
     */
    private String generateChainCertNo(String contractNo) {
        return "CERT-" + contractNo + "-" + System.currentTimeMillis();
    }
    
    /**
     * 初始化蚂蚁链环境
     */
    private void initMychainEnv() throws IOException {
        // 加载用户密钥 - 使用BaaSDepositDemo的方式
        String userPrivateKeyFile = "blockchain/user.key";
        boolean keyLoaded = false;
        
        try {
            log.info("开始加载密钥文件: {}", userPrivateKeyFile);
            
            // 尝试多种方式加载密钥文件
            InputStream keyStream = null;
            
            // 方式1：直接从classpath加载
            keyStream = this.getClass().getClassLoader().getResourceAsStream(userPrivateKeyFile);
            if (keyStream != null && !keyLoaded) {
                log.info("从classpath成功加载密钥文件");
                try {
                    Pkcs8KeyOperator pkcs8KeyOperator = new Pkcs8KeyOperator();
                    byte[] keyBytes = IOUtil.inputStreamToByte(keyStream);
                    log.info("密钥文件大小: {} 字节", keyBytes.length);
                    
                    // 尝试解密密钥
                    try {
                        userKeypair = pkcs8KeyOperator.load(keyBytes, userPassword);
                        log.info("成功解密密钥文件");
                        keyLoaded = true;
                    } catch (Exception e) {
                        log.error("解密密钥文件失败，可能密码不正确: {}", e.getMessage());
                        log.info("尝试使用默认密码解密");
                    }
                } finally {
                    try {
                        keyStream.close();
                    } catch (Exception e) {
                        // 忽略关闭流的异常
                    }
                }
            }
            
            // 方式2：从文件系统加载
            if (!keyLoaded) {
                try {
                    String resourcePath = this.getClass().getClassLoader().getResource("").getPath() + userPrivateKeyFile;
                    File keyFile = new File(resourcePath);
                    if (keyFile.exists()) {
                        log.info("从文件系统加载密钥文件: {}", resourcePath);
                        Pkcs8KeyOperator pkcs8KeyOperator = new Pkcs8KeyOperator();
                        byte[] keyBytes = Files.readAllBytes(keyFile.toPath());
                        log.info("密钥文件大小: {} 字节", keyBytes.length);
                        userKeypair = pkcs8KeyOperator.load(keyBytes, userPassword);
                        log.info("成功解密密钥文件");
                        keyLoaded = true;
                    } else {
                        log.error("密钥文件不存在: {}", resourcePath);
                    }
                } catch (Exception e) {
                    log.error("从文件系统加载密钥失败: {}", e.getMessage());
                }
            }
            
            // 如果所有方式都失败，抛出异常
            if (!keyLoaded) {
                // 方式3：尝试从其他位置加载
                // 例如从配置的绝对路径加载
                // ...
                
                log.warn("所有加载密钥的方式均失败");
                throw new IOException("无法加载密钥文件，请确保文件存在且密码正确");
            }
            
            // 只有成功加载了密钥，才能继续构建环境
            env = buildMychainEnv();
            ILogger logger = AbstractLoggerFactory.getInstance(ContractBlockchainServiceImpl.class);
            env.setLogger(logger);
    
            log.info("===  证书文件检查 ===");
            String[] files = {"blockchain/user.key", "blockchain/client.key", "blockchain/client.crt", "blockchain/trustCa"};
            for (String file : files) {
                InputStream is = this.getClass().getClassLoader().getResourceAsStream(file);
                if (is == null) {
                    log.error("找不到证书文件: {}", file);
                } else {
                    log.info("证书文件存在: {}", file);
                    try {
                        is.close();
                    } catch (IOException e) {
                        log.error("关闭流失败", e);
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("加载用户密钥失败", e);
            log.error("用户密码: {}", userPassword);  // 仅用于调试
            throw new IOException("加载用户密钥失败: " + e.getMessage(), e);
        }
    }

    /**
     * 构建蚂蚁链环境
     */
    private ClientEnv buildMychainEnv() throws IOException {
        InetSocketAddress inetSocketAddress = InetSocketAddress.createUnresolved(blockchainHost, blockchainPort);
        String keyFilePath = "blockchain/client.key";
        String certFilePath = "blockchain/client.crt";
        String trustStoreFilePath = "blockchain/trustCa";

        log.info("构建MyChain环境，连接至: {}:{}", blockchainHost, blockchainPort);
        
        // 使用BaaSDepositDemo的方式加载证书
        byte[] keyBytes = null;
        byte[] certBytes = null;
        byte[] trustStoreBytes = null;
        
        try {
            // 尝试从classpath加载
            log.info("尝试从classpath加载证书文件");
            InputStream keyStream = ContractBlockchainServiceImpl.class.getClassLoader().getResourceAsStream(keyFilePath);
            InputStream certStream = ContractBlockchainServiceImpl.class.getClassLoader().getResourceAsStream(certFilePath);
            InputStream trustStream = ContractBlockchainServiceImpl.class.getClassLoader().getResourceAsStream(trustStoreFilePath);
            
            if (keyStream != null && certStream != null && trustStream != null) {
                log.info("从classpath成功加载所有证书文件");
                keyBytes = IOUtil.inputStreamToByte(keyStream);
                certBytes = IOUtil.inputStreamToByte(certStream);
                trustStoreBytes = IOUtil.inputStreamToByte(trustStream);
                
                log.info("证书文件大小 - key: {} 字节, cert: {} 字节, trust: {} 字节", 
                    keyBytes != null ? keyBytes.length : 0,
                    certBytes != null ? certBytes.length : 0,
                    trustStoreBytes != null ? trustStoreBytes.length : 0);
                
                // 关闭流
                try { keyStream.close(); } catch (Exception e) {}
                try { certStream.close(); } catch (Exception e) {}
                try { trustStream.close(); } catch (Exception e) {}
            } else {
                log.warn("无法从classpath加载所有证书文件，尝试从文件系统加载");
            }
            
            // 如果从classpath加载失败，尝试从文件系统加载
            if (keyBytes == null || certBytes == null || trustStoreBytes == null) {
                String basePath = this.getClass().getClassLoader().getResource("").getPath();
                log.info("尝试从文件系统加载证书文件，基础路径: {}", basePath);
                
                File keyFile = new File(basePath + keyFilePath);
                File certFile = new File(basePath + certFilePath);
                File trustStoreFile = new File(basePath + trustStoreFilePath);
                
                if (keyFile.exists() && certFile.exists() && trustStoreFile.exists()) {
                    log.info("从文件系统成功找到所有证书文件");
                    keyBytes = Files.readAllBytes(keyFile.toPath());
                    certBytes = Files.readAllBytes(certFile.toPath());
                    trustStoreBytes = Files.readAllBytes(trustStoreFile.toPath());
                    
                    log.info("证书文件大小 - key: {} 字节, cert: {} 字节, trust: {} 字节", 
                        keyBytes.length, certBytes.length, trustStoreBytes.length);
                } else {
                    log.error("部分证书文件不存在 - key存在: {}, cert存在: {}, trust存在: {}", 
                        keyFile.exists(), certFile.exists(), trustStoreFile.exists());
                    throw new IOException("无法找到所有必要的证书文件");
                }
            }
        } catch (Exception e) {
            log.error("加载证书文件失败", e);
            throw new IOException("加载证书文件失败: " + e.getMessage(), e);
        }
        
        if (keyBytes == null || certBytes == null || trustStoreBytes == null) {
            throw new IOException("证书文件加载失败，无法继续");
        }
        
        try {
            // 构建SSL选项
            log.info("构建SSL选项");
            ISslOption sslOption = new SslBytesOption.Builder()
                    .keyBytes(keyBytes)
                    .certBytes(certBytes)
                    .keyPassword(keyPassword)
                    .trustStorePassword(trustStorePassword)
                    .trustStoreBytes(trustStoreBytes)
                    .build();
    
            List<InetSocketAddress> socketAddressArrayList = new ArrayList<>();
            socketAddressArrayList.add(inetSocketAddress);
    
            log.info("设置签名器");
            List<SignerBase> signerBaseList = new ArrayList<>();
            SignerBase signerBase = MyCrypto.getInstance().createSigner(userKeypair);
            signerBaseList.add(signerBase);
            SignerOption signerOption = new SignerOption();
            signerOption.setSigners(signerBaseList);
    
            log.info("构建客户端环境完成");
            return ClientEnv.build(socketAddressArrayList, sslOption, signerOption);
        } catch (Exception e) {
            log.error("构建环境失败", e);
            throw new IOException("构建环境失败: " + e.getMessage(), e);
        }
    }

    /**
     * 初始化SDK客户端
     */
    private void initSdk() {
        sdk = new MychainClient();
        boolean initResult = sdk.init(env);
        if (!initResult) {
            throw new RuntimeException("SDK初始化失败");
        }
    }

    /**
     * 数据上链
     */
    private String depositData(String data) {
        log.info("开始上链，数据: " + data);
        log.info("区块链账户: {}", blockchainAccount);
        
        try {
            // 检查账户对象
            if (blockchainAccount == null || blockchainAccount.isEmpty()) {
                throw new RuntimeException("区块链账户名称为空");
            }
            
            if (data.getBytes().length > 1024 * 1024) {
                throw new RuntimeException("数据大小超过1MB限制");
            }
            
            // 检查SDK初始化状态
            if (sdk == null) {
                throw new RuntimeException("SDK未初始化");
            }
            
            if (sdk.getAccountService() == null) {
                throw new RuntimeException("AccountService未初始化");
            }

            // 构建存证交易
            log.info("准备构建存证交易请求");
            DepositDataRequest request = new DepositDataRequest(
                    Utils.getIdentityByName(blockchainAccount), 
                    Utils.getIdentityByName(blockchainAccount), 
                    data.getBytes(), 
                    BigInteger.ZERO);
            
            log.info("开始调用depositData接口");
            DepositDataResponse response = sdk.getAccountService().depositData(request);
            log.info("depositData接口调用完成");
            
            if (!response.isSuccess() || response.getTransactionReceipt().getResult() != 0) {
                log.error("数据上链失败，返回码: {}", response.getTransactionReceipt().getResult());
                throw new RuntimeException("数据上链失败: " + response.getTransactionReceipt().getResult());
        } else {
                String txHash = response.getTxHash().hexStrValue();
                log.info("=====================================================================");
                log.info("交易成功发送到蚂蚁链网络");
                log.info("交易ID: {}", txHash);
                log.info("=====================================================================");
                return txHash;
            }
        } catch (Exception e) {
            log.error("depositData方法执行异常", e);
            throw e; // 重新抛出异常以便上层捕获
        }
    }

    /**
     * 查询交易
     */
    private boolean queryTransaction(String txHash) {
        if (txHash == null || txHash.isEmpty()) {
            throw new RuntimeException("交易哈希为空");
        }

        log.info("开始查询交易状态，交易ID: {}", txHash);
        
        // 查询交易
        Hash hash = new Hash(txHash);
        QueryTransactionResponse queryTransactionResponse = sdk.getQueryService().queryTransaction(hash);
        
        if (!queryTransactionResponse.isSuccess()) {
            log.error("查询交易失败，交易ID: {}", txHash);
            return false;
        } else {
            String txData = new String(queryTransactionResponse.getTransaction().getData());
            log.info("=====================================================================");
            log.info("交易查询成功");
            log.info("交易ID: {}", txHash);
            log.info("交易数据: {}", txData);
            log.info("交易时间: {}", new Date(queryTransactionResponse.getTransaction().getTimestamp()));
            log.info("=====================================================================");
            return true;
        }
    }

    @Override
    public Map<String, Object> verifyUploadedFile(String contractNo, MultipartFile file) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.info("开始验证上传文件，合同编号: {}", contractNo);
            
            // 查询区块链记录
            ContractBlockchain blockchainRecord = contractBlockchainMapper.selectContractBlockchainByContractNo(contractNo);
            if (blockchainRecord == null) {
                throw new RuntimeException("找不到区块链记录，该合同可能尚未上链");
            }
            
            String txHash = blockchainRecord.getTxHash();
            log.info("验证链上交易，交易ID: {}", txHash);
            
            // 获取合同记录（用于获取标题等信息）
            ContractRecord contractRecord = contractRecordService.selectContractRecordByContractNo(contractNo);
            
            // 计算上传文件的哈希
            String currentHash = null;
            try (InputStream inputStream = file.getInputStream()) {
                currentHash = calculateStreamHash(inputStream);
            }
            
            if (currentHash == null || currentHash.isEmpty()) {
                throw new RuntimeException("计算文件哈希失败");
            }
            
            // 获取链上存储的哈希
            String storedHash = blockchainRecord.getContractHash();
            
            // 比对哈希值
            boolean verified = currentHash.equals(storedHash);
            
            log.info("=====================================================================");
            log.info("合同验证结果：{}", verified ? "验证通过" : "验证失败");
            log.info("合同编号：{}", contractNo);
            log.info("交易ID：{}", txHash);
            log.info("当前哈希：{}", currentHash);
            log.info("链上哈希：{}", storedHash);
            log.info("上链时间：{}", blockchainRecord.getChainTime());
            log.info("=====================================================================");
            
            // 添加额外日志用于诊断
            log.info("后端验证返回的是{}, 哈希值是否一致: {}", verified ? "正确" : "错误", verified);
            
            result.put("contractNo", contractNo);
            result.put("contractTitle", contractRecord != null ? contractRecord.getContractTitle() : "未知合同");
            result.put("currentHash", currentHash);
            result.put("storedHash", storedHash);
            result.put("verified", verified);
            result.put("txHash", blockchainRecord.getTxHash());
            result.put("chainTime", blockchainRecord.getChainTime());
            result.put("chainCertNo", blockchainRecord.getChainCertNo());
            
            return result;
        } catch (Exception e) {
            log.error("验证上传文件失败: " + e.getMessage(), e);
            result.put("error", e.getMessage());
            result.put("verified", false);
            
            throw new RuntimeException("验证上传文件失败: " + e.getMessage());
        }
    }

    private static void exit(String tag, String msg) {
        log.error(String.format("%s error : %s ", tag, msg));
    }

    private static String getErrorMsg(int errorCode) {
        int minMychainSdkErrorCode = ErrorCode.SDK_INTERNAL_ERROR.getErrorCode();
        if (errorCode < minMychainSdkErrorCode) {
            return ErrorCode.valueOf(errorCode).getErrorDesc();
        } else {
            return ErrorCode.valueOf(errorCode).getErrorDesc();
        }
    }
} 